//#include "SFML\Graphics.hpp"
//
//#include <Windows.h>
//
//#define VERLET
//
//using namespace sf;
//
//int ScreenWidth = 800;
//int ScreenHeight = 600;
//float radius = 4.0f;
//float meshRadius = 16.0f;
//float coefficientOfRestitution = 0.95f;
//float drag = 0.5f;
//float plasticElastic = 0.0f;
//
//const int gridX = 16;
//
//Shape *ballDisplay = NULL;
//const int BallCount = 128;
//Vector2f pos[BallCount];
//Vector2f p_p[BallCount];
//Vector2f vel[BallCount];
//Vector2f acc[BallCount];
//
//
//
//template <typename T>
//T Lerp(const T&a, const T&b, float alpha)
//{
//	return a + (b - a) * alpha;
//}
//
//float Dot(const Vector2f &a, const Vector2f &b)
//{
//	return a.x * b.x + a.y * b.y;
//}
//
//float VectorLength(const Vector2f &v)
//{
//	return sqrtf(v.x * v.x + v.y * v.y);
//}
//
//Vector2f GetNormalised(Vector2f v)
//{
//	// Divide vector's X and Y by its length
//	float length = VectorLength(v);
//	v.x /= length;
//	v.y /= length;
//	return v;
//}
//
//void BallCollide(int a, int b)
//{
//	Vector2f vectorFrom1To0 = pos[a] - pos[b];
//
//	// 1. Push the balls apart:
//	Vector2f midpoint = (pos[a] + pos[b]) * 0.5f;
//	Vector2f normalFrom1To0 = GetNormalised(vectorFrom1To0);
//
//	pos[a] = midpoint + normalFrom1To0 * radius;
//	pos[b] = midpoint - normalFrom1To0 * radius;
//
//	// 2. Separate velocities
//	Vector2f a1 = Dot(normalFrom1To0, vel[b]) * normalFrom1To0; // Ball 1's vel in dir of collision
//	Vector2f b1 = vel[b] - a1;									// Ball 1's vel perpendicular to collision
//
//	Vector2f a0 = Dot(-normalFrom1To0, vel[a]) * -normalFrom1To0; // Ball 0's vel in dir of collision
//	Vector2f b0 = vel[a] - a0;									  // Ball 0's vel perpendicular to collision
//
//	// 3. Swap collision velocities
//	std::swap(a1, a0);
//
//	// 4. Calculate plastic velocity
//	Vector2f plastic = (vel[a] + vel[b]) * 0.5f;
//
//	// Blend final velocity based on plastic/elastic:
//	vel[a] = Lerp(a0 + b0, plastic, plasticElastic);
//	vel[b] = Lerp(a1 + b1, plastic, plasticElastic);
//}
//
//void ApplyBumper(int dominant, int submissive, float forceDistance)
//{
//	if (dominant == submissive) return;
//
//	float dist = VectorLength(pos[dominant] - pos[submissive]);
//
//	if (dist < forceDistance)
//	{
//		// Set the distance to be the exact distance we want
//		Vector2f domToSub = pos[submissive] - pos[dominant];
//		Vector2f domToSubNormal = GetNormalised(domToSub);
//
//		pos[submissive] = pos[dominant] + domToSubNormal * forceDistance;
//	}
//}
//
//void ApplyLeash(int dominant, int submissive, float forceDistance)
//{
//	if (dominant == submissive) return;
//
//	float dist = VectorLength(pos[dominant] - pos[submissive]);
//
//	if (dist > forceDistance)
//	{
//		// Set the distance to be the exact distance we want
//		Vector2f domToSub = pos[submissive] - pos[dominant];
//		Vector2f domToSubNormal = GetNormalised(domToSub);
//
//		pos[submissive] = pos[dominant] + domToSubNormal * forceDistance;
//	}
//}
//
//void ApplyDistance(int dominant, int submissive, float forceDistance)
//{
//	if (dominant == submissive) return;
//
//	//float dist = VectorLength(pos[dominant] - pos[submissive]);
//
//	//if (dist != forceDistance)
//	{
//		// Set the distance to be the exact distance we want
//		Vector2f domToSub = pos[submissive] - pos[dominant];
//		Vector2f domToSubNormal = GetNormalised(domToSub);
//		Vector2f mid = (pos[submissive] + pos[dominant]) * 0.5f;
//
//		pos[submissive] = mid + domToSubNormal * forceDistance * 0.5f;
//		pos[dominant] = mid - domToSubNormal * forceDistance * 0.5f;
//	}
//}
//
//void ApplyConstraints()
//{
//	for (int i = 1; i < BallCount; ++i)
//	{
//
//		//ApplyLeash(0, i, 200.0f);
//		if (i % gridX != 0)
//			ApplyDistance(i - 1, i, meshRadius * 2.0f);
//
//		if (i >= gridX)
//			ApplyDistance(i - gridX, i, meshRadius * 2);
//
//		if (i % gridX == 0)
//		{
//			pos[i] = Vector2f((i / gridX) * (meshRadius * 2) + 100, (i % gridX) * (meshRadius * 2) + 100);
//		}
//	}
//
//	// Resolve collisions
//	// Ball on ball action
//	{
//		// Detect if they're even touching!
//		for (int i = 0; i < BallCount; ++i)
//		{
//			for (int j = i + 1; j < BallCount; ++j)
//			{
//				Vector2f vectorFrom1To0 = pos[i] - pos[j];
//				float dist = VectorLength(vectorFrom1To0);
//
//				if (dist < radius * 2.0f)
//				{
//					BallCollide(i, j);
//				}
//			}
//		}
//	}
//
//	// Ball to the wall collision
//	for (int i = 0; i < BallCount; ++i)
//	{
//		if (pos[i].y > ScreenHeight - radius)
//		{
//			float err = pos[i].y - (ScreenHeight - radius);
//			pos[i].y = (ScreenHeight - radius) - err;
//
//			vel[i].y = -vel[i].y * coefficientOfRestitution;
//		}
//
//		if (pos[i].y < 0 + radius)
//		{
//			float err = pos[i].y - (0 + radius);
//			pos[i].y = (0 + radius) - err;
//
//			vel[i].y = -vel[i].y * coefficientOfRestitution;
//		}
//
//		if (pos[i].x > ScreenWidth - radius)
//		{
//			float err = pos[i].x - (ScreenWidth - radius);
//			pos[i].x = (ScreenWidth - radius) - err;
//
//			vel[i].x = -vel[i].x * coefficientOfRestitution;
//		}
//
//		if (pos[i].x < 0 + radius)
//		{
//			float err = pos[i].x - (0 + radius);
//			pos[i].x = (0 + radius) - err;
//
//			vel[i].x = -vel[i].x * coefficientOfRestitution;
//		}
//	}
//}
//
//void Update(float deltaT, float time)
//{
//	// Update inputs ...
//
//	// Move user-controlled stuff ...
//
//	// Physics ... 
//	for (int i = 0; i < BallCount; ++i)
//	{
//		// Sum forces:
//		// Gravity
//		//acc[i].y = cosf(time * 0.25f) * 900.8f;
//		//acc[i].x = sinf(time * 0.25f) * 900.8f;
//		acc[i].y = 900.8f;
//#ifdef VERLET
//		// VERLET INTEGRATION
//		//////////////
//
//		Vector2f vel_i = pos[i] - p_p[i];
//		Vector2f newPos = pos[i] + vel_i * 0.95f;
//		p_p[i] = pos[i];
//		pos[i] = newPos;
//
//		pos[i].y += 0.3f;
//
//		//////////////
//#endif
//
//#ifndef VERLET
//		// EULER INTEGRATION!
//		/////////////////////////////
//		// Integrate
//		// dv = a * dt
//		Vector2f dv = acc[i] * deltaT;
//		vel[i] += dv;
//
//		// dp = v * dt
//		Vector2f dp = vel[i] * deltaT;
//		pos[i] += dp;
//
//		// DRAG
//		vel[i] = vel[i] * powf(drag, deltaT);
//		/////////////////////////////////////
//#endif // VERLET
//	}
//
//}
//
//void Render(RenderWindow &win)
//{
//	win.clear(sf::Color(255, 0, 128, 255));
//
//	// Draw stuff here:
//	for (int i = 0; i < BallCount; ++i)
//	{
//		ballDisplay->setPosition(pos[i]);
//		win.draw(*ballDisplay);
//	}
//
//	win.display();
//}
//
//int physicsmain()
//{
//	// New random numbers each time we run:
//	srand(time(0));
//
//	// Create render window
//	VideoMode video(ScreenWidth, ScreenHeight);
//	RenderWindow window(video, "BALL BLAST");
//
//	// Creation of objects in our main function:
//	ballDisplay = new CircleShape(radius);
//	ballDisplay->setOrigin(radius, radius);
//	ballDisplay->setFillColor(sf::Color(224, 255, 0, 255));
//
//	// Initialse ball values:
//	for (int i = 0; i < BallCount; ++i)
//	{
//		pos[i] = Vector2f(rand() % ScreenWidth, rand() % ScreenHeight);
//		pos[i] = Vector2f((i / gridX) * (meshRadius * 2) + 100, (i % gridX) * (meshRadius * 2) + 100);
//		p_p[i] = pos[i];
//		vel[i].x = (rand() % 4001) - 2000;
//		vel[i].y = (rand() % 4001) - 2000;
//		acc[i] = Vector2f(0.f, 0.f);
//	}
//
//	// Create clock for deltaT
//	Clock deltaTimer, timer;
//
//	// Main game loop:
//	while (window.isOpen())
//	{
//		Clock frameLimiter;
//
//		// Calculate deltaT:
//		float deltaT = deltaTimer.getElapsedTime().asSeconds();
//		float time = timer.getElapsedTime().asSeconds();
//		deltaTimer.restart();
//
//		// Message pump:
//		Event e;
//		while (window.pollEvent(e))
//		{
//			if (Event::Closed == e.type)
//			{
//				window.close();
//			}
//
//			/*
//			if (Event::MouseButtonPressed == e.type)
//			{
//			for (int i = 0; i < BallCount; ++i)
//			{
//			vel[i].x *= (rand() % 4001) - 2000;
//			vel[i].y *= (rand() % 4001) - 2000;
//			}
//			}
//			*/
//
//		}
//
//		if (Mouse::isButtonPressed(Mouse::Left))
//		{
//			pos[0].x = Mouse::getPosition(window).x;
//			pos[0].y = Mouse::getPosition(window).y;
//		}
//
//		// Update, render, etc.
//		Update(deltaT, time);
//
//#ifdef VERLET
//		do
//		{
//			ApplyConstraints();
//			::Sleep(1);
//		} while (frameLimiter.getElapsedTime().asMilliseconds() < 16);
//#endif // VERLET
//
//		Render(window);
//
//	}
//
//	return 0;
//}